"""
钉钉 API 封装类
提供所有钉钉 API 调用的统一接口
"""
import requests
import logging
import hmac
import hashlib
import base64
import urllib.parse
import time

_logger = logging.getLogger(__name__)


class DingTalkAPI:
    """钉钉 API 调用封装"""
    
    def __init__(self, app_key, app_secret, agent_id=None):
        self.app_key = app_key
        self.app_secret = app_secret
        self.agent_id = agent_id
        self.base_url = "https://oapi.dingtalk.com"
        self.api_v1_url = "https://api.dingtalk.com/v1.0"
    
    # ==================== Token 管理 ====================
    
    def get_access_token(self):
        """获取企业内部应用的 access_token"""
        url = f"{self.base_url}/gettoken"
        params = {
            "appkey": self.app_key,
            "appsecret": self.app_secret
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                _logger.info(f"✅ 成功获取 Access Token")
                return result['access_token']
            else:
                _logger.error(f"❌ 获取 Token 失败: {result.get('errmsg')}")
                return None
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return None
    
    # ==================== 部门管理 ====================
    
    def get_department_list(self, access_token, dept_id=1):
        """获取子部门列表"""
        url = f"{self.base_url}/topapi/v2/department/listsub"
        
        params = {"access_token": access_token}
        data = {"dept_id": dept_id}
        
        try:
            _logger.info(f"🔍 正在获取部门列表，dept_id: {dept_id}")
            _logger.info(f"   URL: {url}")
            _logger.info(f"   Data: {data}")
            
            response = requests.post(url, params=params, json=data, timeout=10)
            result = response.json()
            
            _logger.info(f"📡 API 响应: {result}")
            
            if result.get('errcode') == 0:
                # 处理两种可能的响应格式
                result_data = result.get('result', [])
                
                # 如果 result 是字典且包含 list 键
                if isinstance(result_data, dict) and 'list' in result_data:
                    dept_list = result_data['list']
                # 如果 result 直接是列表
                elif isinstance(result_data, list):
                    dept_list = result_data
                else:
                    dept_list = []
                
                _logger.info(f"✅ 成功获取 {len(dept_list)} 个部门")
                return dept_list
            else:
                _logger.error(f"❌ 获取部门列表失败")
                _logger.error(f"   错误码: {result.get('errcode')}")
                _logger.error(f"   错误信息: {result.get('errmsg')}")
                _logger.error(f"   完整响应: {result}")
                return []
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            import traceback
            _logger.error(traceback.format_exc())
            return []
    
    def get_all_departments(self, access_token):
        """递归获取所有部门"""
        all_departments = []
        
        def get_sub_departments(dept_id):
            departments = self.get_department_list(access_token, dept_id)
            for dept in departments:
                all_departments.append(dept)
                # 递归获取子部门
                get_sub_departments(dept['dept_id'])
        
        # 从根部门开始
        get_sub_departments(1)
        return all_departments
    
    def get_department_detail(self, access_token, dept_id):
        """获取部门详细信息"""
        url = f"{self.base_url}/topapi/v2/department/get"
        
        params = {"access_token": access_token}
        data = {"dept_id": dept_id}
        
        try:
            response = requests.post(url, params=params, json=data, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                return result.get('result')
            else:
                _logger.error(f"❌ 获取部门详情失败: {result.get('errmsg')}")
                return None
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return None
    
    # ==================== 用户管理 ====================
    
    def get_department_user_list(self, access_token, dept_id):
        """获取部门用户ID列表"""
        url = f"{self.base_url}/topapi/user/listid"
        
        params = {"access_token": access_token}
        data = {"dept_id": dept_id}
        
        try:
            response = requests.post(url, params=params, json=data, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                return result.get('result', {}).get('userid_list', [])
            else:
                _logger.error(f"❌ 获取用户列表失败: {result.get('errmsg')}")
                return []
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return []
    
    def get_user_detail(self, access_token, userid):
        """获取用户详细信息"""
        url = f"{self.base_url}/topapi/v2/user/get"
        
        params = {"access_token": access_token}
        data = {"userid": userid}
        
        try:
            response = requests.post(url, params=params, json=data, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                return result.get('result')
            else:
                _logger.error(f"❌ 获取用户详情失败: {result.get('errmsg')}")
                return None
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return None
    
    # ==================== 消息发送 ====================
    
    def send_interactive_card(self, access_token, userid_list, card_data):
        """发送互动卡片消息"""
        url = f"{self.base_url}/topapi/message/corpconversation/asyncsend_v2"
        
        params = {"access_token": access_token}
        
        data = {
            "agent_id": self.agent_id,
            "userid_list": ",".join(userid_list) if isinstance(userid_list, list) else userid_list,
            "msg": {
                "msgtype": "action_card",
                "action_card": card_data
            }
        }
        
        try:
            response = requests.post(url, params=params, json=data, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                task_id = result.get('task_id')
                _logger.info(f"✅ 互动卡片发送成功，任务ID: {task_id}")
                return {'success': True, 'task_id': task_id}
            else:
                _logger.error(f"❌ 发送互动卡片失败: {result.get('errmsg')}")
                return {'success': False, 'error': result.get('errmsg')}
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def send_org_robot_message(self, access_token, robot_code, user_ids, msg_param, msg_key='sampleMarkdown'):
        """发送企业内部机器人消息（单聊）- 使用新版 API"""
        import json
        
        url = f"{self.api_v1_url}/robot/oToMessages/batchSend"
        
        headers = {
            "x-acs-dingtalk-access-token": access_token,
            "Content-Type": "application/json"
        }
        
        # 确保 msg_param 是字典类型
        if isinstance(msg_param, str):
            try:
                msg_param = json.loads(msg_param)
            except:
                msg_param = {"content": msg_param}
        
        # 将消息参数转为 JSON 字符串（钉钉 API 要求）
        msg_param_str = json.dumps(msg_param, ensure_ascii=False)
        
        # 准备消息内容
        data = {
            "robotCode": robot_code,
            "userIds": user_ids.split(',') if isinstance(user_ids, str) else user_ids,
            "msgKey": msg_key,
            "msgParam": msg_param_str  # 必须是 JSON 字符串
        }
        
        try:
            _logger.info(f"🤖 发送企业机器人消息")
            _logger.info(f"   URL: {url}")
            _logger.info(f"   RobotCode: {robot_code}")
            _logger.info(f"   UserIds: {data['userIds']}")
            _logger.info(f"   MsgKey: {msg_key}")
            _logger.info(f"   MsgParam: {msg_param_str}")
            
            response = requests.post(url, headers=headers, json=data, timeout=10)
            result = response.json()
            
            _logger.info(f"📡 API 响应: {result}")
            
            # 钉钉新版 API 成功时没有 errcode，直接返回数据
            if 'processQueryKey' in result or 'result' in result:
                _logger.info(f"✅ 企业机器人消息发送成功")
                return {'success': True, 'result': result}
            elif result.get('code') == '0' or not result.get('code'):
                # 有些 API 返回 code 字段
                _logger.info(f"✅ 企业机器人消息发送成功")
                return {'success': True, 'result': result}
            else:
                error_msg = result.get('message') or result.get('errmsg', '未知错误')
                _logger.error(f"❌ 企业机器人消息发送失败: {error_msg}")
                _logger.error(f"   完整响应: {result}")
                return {'success': False, 'error': error_msg}
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            import traceback
            _logger.error(traceback.format_exc())
            return {'success': False, 'error': str(e)}
    
    def send_org_robot_batch_message(self, access_token, robot_code, msg_param):
        """发送企业内部机器人批量消息"""
        url = f"{self.base_url}/topapi/robot/message/sendbyapp"
        
        params = {"access_token": access_token}
        
        data = {
            "robot_code": robot_code,
            "msg_param": msg_param,
            "msg_key": "sampleMarkdown"
        }
        
        try:
            response = requests.post(url, params=params, json=data, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                _logger.info(f"✅ 企业机器人批量消息发送成功")
                return {'success': True}
            else:
                _logger.error(f"❌ 企业机器人批量消息发送失败: {result.get('errmsg')}")
                return {'success': False, 'error': result.get('errmsg')}
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def send_work_notification(self, access_token, userid_list, msg_content, msg_type='markdown'):
        """发送工作通知"""
        url = f"{self.base_url}/topapi/message/corpconversation/asyncsend_v2"
        
        params = {"access_token": access_token}
        
        # 构建消息体
        if msg_type == 'markdown':
            msg = {
                "msgtype": "markdown",
                "markdown": msg_content  # {'title': '...', 'text': '...'}
            }
        elif msg_type == 'text':
            msg = {
                "msgtype": "text",
                "text": {"content": msg_content}
            }
        elif msg_type == 'link':
            msg = {
                "msgtype": "link",
                "link": msg_content  # {'title': '...', 'text': '...', 'messageUrl': '...'}
            }
        else:
            msg = msg_content  # 自定义消息体
        
        data = {
            "agent_id": self.agent_id,
            "userid_list": ",".join(userid_list) if isinstance(userid_list, list) else userid_list,
            "msg": msg
        }
        
        try:
            response = requests.post(url, params=params, json=data, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                task_id = result.get('task_id')
                _logger.info(f"✅ 工作通知发送成功，任务ID: {task_id}")
                return {'success': True, 'task_id': task_id}
            else:
                _logger.error(f"❌ 发送工作通知失败: {result.get('errmsg')}")
                return {'success': False, 'error': result.get('errmsg')}
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def send_robot_message(self, webhook_url, secret, content, msg_type='markdown', at_mobiles=None, at_all=False):
        """通过自定义机器人发送消息"""
        # 计算签名
        timestamp = str(round(time.time() * 1000))
        secret_enc = secret.encode('utf-8')
        string_to_sign = f'{timestamp}\n{secret}'
        string_to_sign_enc = string_to_sign.encode('utf-8')
        hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
        sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
        
        # 构建完整 URL
        url = f"{webhook_url}&timestamp={timestamp}&sign={sign}"
        
        # 构建消息
        if msg_type == 'markdown':
            msg = {
                "msgtype": "markdown",
                "markdown": content  # {'title': '...', 'text': '...'}
            }
        elif msg_type == 'text':
            msg = {
                "msgtype": "text",
                "text": {"content": content}
            }
        else:
            msg = content
        
        # 添加 @ 信息
        if at_mobiles or at_all:
            msg['at'] = {
                "atMobiles": at_mobiles or [],
                "isAtAll": at_all
            }
        
        try:
            response = requests.post(url, json=msg, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                _logger.info(f"✅ 机器人消息发送成功")
                return {'success': True}
            else:
                _logger.error(f"❌ 机器人消息发送失败: {result.get('errmsg')}")
                return {'success': False, 'error': result.get('errmsg')}
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def send_group_message(self, access_token, chatid, content, msg_type='text'):
        """发送群消息"""
        url = f"{self.base_url}/chat/send"
        
        params = {"access_token": access_token}
        
        # 构建消息
        if msg_type == 'text':
            msg = {
                "msgtype": "text",
                "text": {"content": content}
            }
        elif msg_type == 'markdown':
            msg = {
                "msgtype": "markdown",
                "markdown": content
            }
        else:
            msg = content
        
        data = {
            "chatid": chatid,
            "msg": msg
        }
        
        try:
            response = requests.post(url, params=params, json=data, timeout=10)
            result = response.json()
            
            if result.get('errcode') == 0:
                _logger.info(f"✅ 群消息发送成功")
                return {'success': True}
            else:
                _logger.error(f"❌ 群消息发送失败: {result.get('errmsg')}")
                return {'success': False, 'error': result.get('errmsg')}
                
        except Exception as e:
            _logger.error(f"❌ 请求异常: {str(e)}")
            return {'success': False, 'error': str(e)}

